iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 21
0

本篇擷取重點:

  1. 網頁跳轉的比較
    • Response.Redirect()
    • Server.Transfer()
    • Server.Execute()
  2. 網頁跳轉的個別示範

一、網頁跳轉的基礎比較總覽

比較項 Response.Redirect() Server.Transfer() Server.Execute()
目的地 可以切換到任何的網頁 只能切換到同目錄或子目錄的網頁 同Transfer()
安全性 url會變成你所指向的新網頁 url不變,隱藏了新網頁的url及附帶的參數值 同Transfer()
傳遞容量 受各瀏覽器的網址欄位長度限制(含傳遞引數) 同Transfer()
連接伺服器 來回伺服器兩次,故較受網路連線品質影響。 僅來回伺服器僅一次,於伺服器內進行轉址的動作。 同Transfer()

那麼,Server.Transfer()及 Server.Execute() 的差異為何呢?

Server.Execute()和Server.Transfer功能很相像。但主要的差別在,Execute在轉到新頁面執行完成後,會回到原頁面,插入新頁面輸出結果並【繼續】執行原頁面的後續程式碼。而Transfer在轉到新頁面並執行完成新頁面的輸出後,就並【不會繼續】執行原頁面的後續程式碼

==================================================================
貼心小補充,連接伺服器的次數

Response.Redirect()
這個跳轉頁面的方法跳轉的速度不快,因為它要走2個來回,但他可以跳轉到任何頁面,沒有站點頁面限制(即可以由雅虎跳到新浪),它需要重新驗證登入保護,因為已視為一個全新的網站連結。

Redirect跳轉機制:首先是傳送一個http請求到客戶端,通知需要跳轉到新頁面,然後客戶端在傳送跳轉請求到伺服器端。需要注意的是跳轉後內部空間儲存的所有資料資訊將會丟失,所以需要用到session

https://ithelp.ithome.com.tw/upload/images/20190922/20120056r4wpPF72u0.jpg


Server.Transfer()
速度相對較快,因為它只需走1個來回,但他必須是跳轉在同一個站點下的頁面,因為它是server的一個方法。另外,它無須重新驗證登入保護,因為只是從同一個網站下的一個頁面移動至另一個頁面。另外,若希望藉由隱藏網址來達到保護網頁的保密功能,實務上多是使用HttpContext.RewritePath()來做 URL Rewriting (也就是保持網頁的 URL 不變)。

https://ithelp.ithome.com.tw/upload/images/20190922/20120056JFGLripBPw.jpg

延伸閱讀:
https://www.developerfusion.com/article/4643/implementing-http-handlers-in-aspnet/4/
https://stackoverflow.com/questions/336813/server-transfer-vs-context-rewritepath


Sever.Execute()
這個方法主要是用在頁面設計上面,而且他必須是跳轉同一站點下的頁面。這個方法是需要將一個頁面的輸出結果插入到另一個aspx頁面的時候使用,大部分是在表格中,將某一個頁面類似於巢狀的方式存在於另一頁面。

參考資料:
https://codertw.com/%E5%89%8D%E7%AB%AF%E9%96%8B%E7%99%BC/199321/
https://dotblogs.com.tw/jimmyyu/archive/2009/11/10/11503.aspx (大推薦)

==================================================================


二、網頁跳轉的個別示範

為了瞭解網頁跳轉的實際作用及執行順序,我們須先完成一些預備動作,方便查看。

  1. 首先另外新增一個Web表單方便跳轉,命名為detail.aspx

在detail.aspx.cs程式碼後置檔案中,顯示字串,this message is in detail.aspx

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace ShareTwo
{
    public partial class detail : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Response.Write("detail.aspx.cs的內容");
        }
    }
}

在detail.aspx設計頁面中,顯示字串,detail.aspx

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="detail.aspx.cs" Inherits="ShareTwo.detail" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
        <div>
            <span>detail.aspx的內容</span>
        </div>
    </form>
</body>
</html>
  1. 在原本的Web表單(default.aspx)的設計頁面,顯示字串,default.aspx
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="default.aspx.cs" Inherits="ShareTwo._default" %>

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
    <title></title>
</head>
<body>
<form id="form1" runat="server">
    <div>
        <span>default.aspx的內容</span>
    </div>
</form>
</body>
</html>

好了,我們的預備動作告一段落,接下來進行的測試都放在原頁面的後置程式碼檔案中(default.aspx.cs)

  1. Response.Redirect

此方法將直接轉至新網址(不受限於同一站點內),故上方原頁面的輸出內容並不會出現在跳轉後的頁面。

Response.Write("Response.Redirect方法:");
Response.Redirect("detail.aspx");
Response.Write("測試 Redirect");

頁面顯示:
https://ithelp.ithome.com.tw/upload/images/20190922/20120056fKDw6EjM1K.jpg

值得注意的,如下

  • 網址顯示為新頁面的網址,https: //localhost:44381/detail.aspx
  • 由於在Response.Redirect("detail.aspx")時,已離開原頁面(default.aspx)轉至新頁面(detail.aspx),故只顯示新頁面的內容,且依序為新頁面後置程式碼檔案中(detail.aspx.cs)→新頁面設計頁面(detail.aspx)。

  1. Server.Transfer

Transfer在轉到新頁面並執行完成新頁面的輸出後,就並【不會繼續】執行原頁面的後續程式碼,故下方的原頁面輸出內容(測試 Transfer)並不會出現。

Response.Write("Transfer方法:"); 
Server.Transfer("detail.aspx"); 
Response.Write("測試 Transfer");

頁面顯示:
https://ithelp.ithome.com.tw/upload/images/20190922/201200567doaZGegP9.jpg

值得注意的,如下

  • 網址顯示仍為原頁面的網址,https: //localhost:44381/default.aspx
  • 由於在Response.Transfer("detail.aspx")時,由於頁面的轉跳都在伺服器內完成,由伺服器直接傳輸新頁面的內容給瀏覽器,但瀏覽器並不知道頁面已經轉跳,所以以為接受地的內容皆屬於原頁面,故原頁面跳轉前的輸出內容及新頁面的輸出內容都會一併顯示在原頁面上,且依序為跳轉前的原頁面後置程式碼檔案中(default.aspx.cs)→新頁面後置程式碼檔案中(detail.aspx.cs)→新頁面設計頁面(detail.aspx)。

  1. Server.Execute

Execute在轉到新頁面執行完成後,會回到原頁面,插入新頁面輸出結果並【繼續】執行原頁面的後續程式碼。

==================================================================
**貼心小補充,感謝朱大補充

不過,Server.Execute() 其實也不是設計用來跳轉的,它主要的目的是在 ASP.NET 內執行別的網頁 (例如執行交易的網頁) 再將結果寫入到 Response 內,例如要在一個要求內同時對不同的 aspx 做叫用時,只需要發一個要求就可以在程式內叫用 Server.Execute() 對其他要操作的頁面做呼叫,而回傳時只會看到執行結果,因此有可能是有結果 (有輸出) 或沒有結果 (沒有輸出) 的情況,不過在近幾年來的演進,已經幾乎不使用 Server.Execute() 了,而是改用 HTTP client 去叫用,這樣的好處是可以得到執行結果做進一步處理 (即便被叫用的aspx是在同一個專案的也是),但 Server.Execute() 是直接把結果寫入到 Response,程式連處理的機會都沒有。只能說 Server.Execute() 比較像是要相容 ASP 的舊思維才保留的吧。

==================================================================

Response.Write(".Execute方法:");//在不變更URL下,將頁面轉至同伺服器底下的其他網頁,執行完畢後將回到原本.aspx "繼續執行"
Server.Execute("detail.aspx");// detail.aspx 這頁面內容為 this message is in detail.aspx
Response.Write("測試 Execute");

頁面顯示:
https://ithelp.ithome.com.tw/upload/images/20190922/20120056s4uGfLkNYb.jpg

值得注意的,如下

  • 網址顯示仍為原頁面的網址,https: //localhost:44381/default.aspx
  • 由於在Response.Execute("detail.aspx")時,由於頁面的轉跳都在伺服器內完成,由伺服器直接傳輸新頁面的內容給瀏覽器,但瀏覽器並不知道頁面已經轉跳,所以以為接受地的內容皆屬於原頁面,故原頁面跳轉前的輸出內容及新頁面的輸出內容都會一併顯示在原頁面上,另外依Execute方法的特性,跳轉至新頁面執行完後,還會返回到原頁面繼續執行執行。依序為跳轉前的原頁面後置程式碼檔案中(default.aspx.cs)→新頁面後置程式碼檔案中(detail.aspx.cs)→新頁面設計頁面(detail.aspx)→跳轉後的原頁面後置程式碼檔案中(default.aspx.cs)→原頁面設計頁面(default.aspx)。

此篇內容整理自多篇網路文章、PPT及自己的理解,但筆者也仍處在初階的學習過程,對程式概念的理解及判斷都尚不足,若有錯誤的地方,也煩請各位大大提點,先謝謝大家惹!!


明日(9/23)預定探討課題:

網頁暫存(Application、Session、Cookie、Cache)


上一篇
[ASP.NET] 網頁常用物件-初淺談Server物件
下一篇
[ASP.NET] 網頁常用物件-網頁資料儲存方式(Application、Session、Cookie、Cache)
系列文
ASP.NET Web Form 入門30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

2
小朱
iT邦新手 4 級 ‧ 2019-09-22 20:32:43
  1. Execute在轉到新頁面執行完成後,會回到原頁面,插入新頁面輸出結果並【繼續】編譯原頁面的後續程式碼。而Transfer在轉到新頁面並執行完成新頁面的輸出後,就並【不會繼續】編譯原頁面的後續程式碼。

這一段用 "編譯" 怪怪的,應該是 "執行" 才對,編譯在 ASP.NET 只會在第一次執行時才會有所謂的即時編譯 (JIT, 將 MSIL code 編譯成 native code),第二次以後就不會再編譯,直到 IIS 在閒置時間到時釋放所有 DLL 後又再次被喚起,才會又再做一次 JIT 編譯。

  1. Response.Redirect() 這個跳轉頁面的方法跳轉的速度不快,因為它要走2個來回(2次postback),但他可以跳轉到任何頁面...

這有點誤解,Response.Redirect 是傳給用戶端 HTTP 302 (REDIRECT) 指令,由瀏覽器做跳轉,另外,PostBack 和要求 (Request) 雖然很像但行為有一點差異,PostBack也是一種要求,但PostBack會帶網頁上的ViewState回Server,Server會判斷要求中有沒有這項資訊,有的話才會把 IsPostBack設為true,但單純的要求不算是PostBack (包含第一次的aspx要求)。

  1. Server.Transfer() 基本上不是用來保護網頁的,但它早期在還沒有 RewritePath() 時確實會被用來做隱藏網址的手段,但因為它會擲出 ThreadAbortException,所以目前實務上多是使用
    HttpContext.RewritePath() 來做 URL Rewriting (也就是保持網頁的 URL 不變)。

可參考:
https://www.developerfusion.com/article/4643/implementing-http-handlers-in-aspnet/4/
https://stackoverflow.com/questions/336813/server-transfer-vs-context-rewritepath

  1. Server.Execute() 其實也不是設計用來跳轉的,它主要的目的是在 ASP.NET 內執行別的網頁 (例如執行交易的網頁) 再將結果寫入到 Response 內,例如要在一個要求內同時對不同的 aspx 做叫用時,只需要發一個要求就可以在程式內叫用 Server.Execute() 對其他要操作的頁面做呼叫,而回傳時只會看到執行結果,因此有可能是有結果 (有輸出) 或沒有結果 (沒有輸出) 的情況,不過在近幾年來的演進,已經幾乎不使用 Server.Execute() 了,而是改用 HTTP client 去叫用,這樣的好處是可以得到執行結果做進一步處理 (即便被叫用的aspx是在同一個專案的也是),但 Server.Execute() 是直接把結果寫入到 Response,程式連處理的機會都沒有。只能說 Server.Execute() 比較像是要相容 ASP 的舊思維才保留的吧。

謝謝朱大,讓我開了很多觀念(編譯、postback...等),還補充了HttpContext.RewritePath()的用法及分享Server.Execute()設計概念與我們會在實務上的作法

我要留言

立即登入留言